package com.icbc.digitalwallet.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.icbc.digitalwallet.common.enums.BankCodeEnum;
import com.icbc.digitalwallet.common.enums.ResponseEnum;
import com.icbc.digitalwallet.common.enums.TransTypeEnum;
import com.icbc.digitalwallet.common.exception.Assert;
import com.icbc.digitalwallet.common.exception.BusinessException;
import com.icbc.digitalwallet.common.util.GetYearMonthWeek;
import com.icbc.digitalwallet.common.util.MD5;
import com.icbc.digitalwallet.common.util.RandomUtils;
import com.icbc.digitalwallet.common.util.TransNoUtils;
import com.icbc.digitalwallet.mapper.BankAccountMapper;
import com.icbc.digitalwallet.mapper.TransFlowMapper;
import com.icbc.digitalwallet.pojo.VO.TransVO;
import com.icbc.digitalwallet.pojo.entity.BankAccount;
import com.icbc.digitalwallet.pojo.entity.Card;
import com.icbc.digitalwallet.pojo.entity.DigitalWallet;
import com.icbc.digitalwallet.mapper.DigitalWalletMapper;
import com.icbc.digitalwallet.pojo.entity.TransFlow;
import com.icbc.digitalwallet.service.DigitalWalletService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author tx
 * @since 2021-07-17
 */
@Service
public class DigitalWalletServiceImpl extends ServiceImpl<DigitalWalletMapper, DigitalWallet> implements DigitalWalletService {

    @Autowired
    private BankAccountMapper bankAccountMapper;

    @Autowired
    private TransFlowMapper transFlowMapper;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void reCharge(String walletId, TransVO transVO) {
        //转账操作
//========校验参数========================================================
        //获取输入的支付密码
        String password = transVO.getPayPassword();
        Assert.notEmpty(password,ResponseEnum.TRANS_PAYPASSWORD_EMPTY_ERROR);

        //查询钱包账户
        DigitalWallet wallet = baseMapper.selectById(walletId);
        if (wallet==null){
            throw new BusinessException("请先登录");
        }
        //获取数字钱包的支付密码
        String payPassword = wallet.getPayPassword();
        //验证支付密码 不正确则抛异常
        if (!payPassword.equals(MD5.encrypt(password))){
//            throw new BusinessException("支付密码错误");
            throw new BusinessException(ResponseEnum.PASSWORD_ERROR);
        }

        //交易金额
        BigDecimal amount = transVO.getAmount();
        if (amount==null || amount.compareTo(new BigDecimal("0")) != 1){
//            throw new BusinessException("充值金额异常");
            throw new BusinessException(ResponseEnum.RECHARGE_AMOUNT_ERROR);
        }

        //交易对象账户的id 此处是银行账号
        String transObjId = transVO.getTransObjId();
        Assert.notEmpty(transObjId,ResponseEnum.TRANS_OBJ_EMPTY_ERROR);

        //根据id查询银行账户
        BankAccount bankAccount = bankAccountMapper.selectById(transObjId);
        Assert.notNull(bankAccount,ResponseEnum.TRANS_OBJ_NULL_ERROR);
        if (amount.compareTo(bankAccount.getAmount()) == 1){
//            throw new BusinessException("银行卡账户余额不足");
            throw new BusinessException(ResponseEnum.ACCOUNT_BALANCE_ERROR);
        }

//========= 转账操作=====================================================================
        //银行卡余额
        BigDecimal bankAccountAmount = bankAccount.getAmount();
        //银行卡减去交易金额
        bankAccount.setAmount(bankAccountAmount.subtract(amount));
        bankAccountMapper.updateById(bankAccount);
        //数字钱包加上充值金额
        BigDecimal walletAmount = wallet.getAmount();
        wallet.setAmount(walletAmount.add(amount));
        baseMapper.updateById(wallet);

//============交易流水=====================================================
        //记录用户交易流水
        TransFlow transFlowUser = new TransFlow();
        transFlowUser.setUserId(wallet.getDwId());
        transFlowUser.setTransObj(bankAccount.getAccId());
        //设置交易对象
        //设置银行的昵称 银行名称+账户后四位
        String bankAccountName = BankCodeEnum.getBankName(bankAccount.getBankCode())+"尾号"+bankAccount.getAccId().substring(bankAccount.getAccId().length()-4);
        transFlowUser.setTransObjName(bankAccountName);
        //设置交易类型 0充值 1提现 2转入 3 转出 在枚举TransTypeEnum中
        transFlowUser.setTransType(TransTypeEnum.RECHARGE.getTransType());
        //交易金额
        transFlowUser.setAmount(amount);
        //交易流水单号
        String transNo = TransNoUtils.getNo();
        transFlowUser.setTransNo(transNo);
        //交易结果
        transFlowUser.setTransResult(true);
        transFlowMapper.insert(transFlowUser);

        //记录交易对象流水
        TransFlow transFlowObj = new TransFlow();
        transFlowObj.setUserId(bankAccount.getAccId());
        transFlowObj.setTransObj(wallet.getDwId());
        transFlowObj.setTransObjName(wallet.getNickName());
        transFlowObj.setTransType(TransTypeEnum.TRANS_OUT.getTransType());
        //交易金额
        transFlowObj.setAmount(amount);
        //流水
        transFlowObj.setTransNo(transNo);
        transFlowObj.setTransResult(true);
        transFlowMapper.insert(transFlowObj);

    }

    @Override
    public DigitalWallet getUserInfoById(String id) {
        DigitalWallet wallet = baseMapper.getUserInfoById(id);
        return wallet;
    }

    @Override
    public void withDraw(String walletId, TransVO transVO) {
//============校验参数========================================

        //获取输入的支付密码
        String password = transVO.getPayPassword();
        Assert.notEmpty(password,ResponseEnum.TRANS_PAYPASSWORD_EMPTY_ERROR);

        //查询钱包账户
        DigitalWallet wallet = baseMapper.selectById(walletId);
        if (wallet==null){
            throw new BusinessException("请先登录");
        }
        //获取数字钱包的支付密码
        String payPassword = wallet.getPayPassword();
        //验证支付密码 不正确则抛异常
        if (!payPassword.equals(MD5.encrypt(password))){
//            throw new BusinessException("支付密码错误");
            throw new BusinessException(ResponseEnum.PASSWORD_ERROR);
        }

        //交易金额为空 金额为0 金额大于账户余额 提示异常
        BigDecimal amount = transVO.getAmount();
        if (amount==null || amount.compareTo(new BigDecimal("0")) !=1 || amount.compareTo(wallet.getAmount())==1){
//            throw new BusinessException("提现金额异常");
            throw new BusinessException(ResponseEnum.WITHDRAW_AMOUNT_ERROR);
        }

        //交易对象账户的id 此处是银行账号
        String transObjId = transVO.getTransObjId();
        Assert.notEmpty(transObjId,ResponseEnum.TRANS_OBJ_EMPTY_ERROR);
        //根据id查询银行账户
        BankAccount bankAccount = bankAccountMapper.selectById(transObjId);
        Assert.notNull(bankAccount,ResponseEnum.TRANS_OBJ_NULL_ERROR);

//============转账操作================================================
        //银行卡余额
        BigDecimal bankAccountAmount = bankAccount.getAmount();
        //银行卡加上交易金额
        bankAccount.setAmount(bankAccountAmount.add(amount));
        bankAccountMapper.updateById(bankAccount);
        //数字钱包减去提现金额
        BigDecimal walletAmount = wallet.getAmount();
        wallet.setAmount(walletAmount.subtract(amount));
        baseMapper.updateById(wallet);

//============业务流水================================================
        //记录用户交易流水
        TransFlow transFlowUser = new TransFlow();
        transFlowUser.setUserId(wallet.getDwId());
        transFlowUser.setTransObj(bankAccount.getAccId());
        //设置交易对象名称
        String bankAccountName = BankCodeEnum.getBankName(bankAccount.getBankCode())+"尾号"+bankAccount.getAccId().substring(bankAccount.getAccId().length()-4);
        transFlowUser.setTransObjName(bankAccountName);
//        transFlowUser.setTransObjName(bankAccount.getBankCode());
        //设置交易类型 0充值 1提现 2转入 3 转出 在枚举TransTypeEnum中
        transFlowUser.setTransType(TransTypeEnum.WITHDRAW.getTransType());
        //交易金额
        transFlowUser.setAmount(amount);
        //交易流水单号
        String transNo = TransNoUtils.getNo();
        transFlowUser.setTransNo(transNo);
        //交易结果
        transFlowUser.setTransResult(true);
        transFlowMapper.insert(transFlowUser);

        //记录交易对象流水
        TransFlow transFlowObj = new TransFlow();
        transFlowObj.setUserId(bankAccount.getAccId());
        transFlowObj.setTransObj(wallet.getDwId());
        transFlowObj.setTransObjName(wallet.getNickName());
        transFlowObj.setTransType(TransTypeEnum.TRANS_IN.getTransType());
        //交易金额
        transFlowObj.setAmount(amount);
        //流水
        transFlowObj.setTransNo(transNo);
        transFlowObj.setTransResult(true);
        transFlowMapper.insert(transFlowObj);

    }

    @Override
    public List<TransFlow> getTransFlow(String id,Integer type) {

        QueryWrapper<TransFlow> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",id);
        if (type!=null){
            wrapper.eq("trans_type",type);
        }
        wrapper.orderByDesc("create_time");
        List<TransFlow> transFlowList = transFlowMapper.selectList(wrapper);
        for (TransFlow transFlow : transFlowList) {
            transFlow.setTransTypeName(TransTypeEnum.getTransTypeName(transFlow.getTransType()));
            transFlow.setYear(GetYearMonthWeek.getYear(transFlow.getCreateTime()));
            transFlow.setMonth(GetYearMonthWeek.getMonth(transFlow.getCreateTime()));
            transFlow.setDays(GetYearMonthWeek.getDay(transFlow.getCreateTime()));
            transFlow.setWeek(GetYearMonthWeek.getWeek(transFlow.getCreateTime()));
            if (transFlow.getTransType()==0|| transFlow.getTransType()==2){
                transFlow.setResultAmount("+"+transFlow.getAmount());
            }else {
                transFlow.setResultAmount("-"+transFlow.getAmount());
            }
            transFlow.setTransObj(null);
            transFlow.setAmount(null);
            transFlow.setTransType(null);
            transFlow.setMemo(null);
            transFlow.setTransNo(null);
            transFlow.setTransResult(null);
            transFlow.setCreateTime(null);
            transFlow.setUpdateTime(null);

        }
        return transFlowList;
    }

    @Override
    public List<BankAccount> getCardsInfo(String id) {
        List<BankAccount> bankAccountList = baseMapper.getCardsInfo(id);
        //进行一些转换
        //将银行代码转为银行名称传给前端
        //前端不需要转换
//        for (BankAccount bankAccount : bankAccountList) {
//            bankAccount.setBankName(BankCodeEnum.getBankName(bankAccount.getBankCode()));
//        }

        return bankAccountList;
    }

    @Override
    public String getRechargeKey() {
        String reChargeKey = RandomUtils.getSixBitRandom();
        //可设置超时时间  实现逻辑是在执行完业务后会将缓存删除
        redisTemplate.opsForValue().set(reChargeKey,"1");
        return reChargeKey;
    }
}
